Semantik Web • Hafta 09
OWL API — II & Reasoner'lar
Çıkarım kuramı, HermiT · Pellet · JFact · ELK, SWRL motorları ve alerji ontolojisinde risk çıkarımı
Lisansüstü Semantik Web Dersi • CMPE 583
Hafta 09 • Kazanımlar
Bu hafta sonunda
- Reasoner'ın üç temel görevini ve nasıl çalıştığını açıklayabileceksiniz.
- HermiT, Pellet/Openllet, JFact ve ELK arasında bilinçli seçim yapabileceksiniz.
- OWLReasoner arayüzünü kısa kod parçalarıyla kullanabileceksiniz.
- SWRL motoru ile DL reasoner'ın iş bölümünü kurabileceksiniz.
- Çıkarımı kalıcı hâle getirip tutarsızlığı gerekçesiyle bulabileceksiniz.
01
Ödev 8'in Çözümü
EAN_00005'in kodla eklenmesi.
Çözüm 8.1 — Doğru metot adları
getOWLClassAssertionAxiom(
cls("Product"), ind("EAN_00005"));
getOWLObjectPropertyAssertionAxiom(
op("Contain"), ind("EAN_00005"),
ind("Whey_Protein"));
getOWLObjectPropertyAssertionAxiom(
op("Triggers"), ind("Whey_Protein"),
ind("Lactose"));
- 5 aksiyom: 1 tip + 2 Contain + 2 Triggers.
- S6 tetiklenir: TC_001 (Lactose) ve TC_004 (Gluten) bu ürünü seçerse.
- Declaration gerekmez: assertion varlığı ima eder.
02
Çıkarım Nedir?
Reasoner ne yapar, nasıl yapar, neyi garanti eder.
Mantıksal sonuç (entailment)
Bir ontoloji O, bir aksiyom A'yı gerektirir (O ⊨ A) demek: O'yu doğru kılan her yorumda A da doğrudur.
Verili: Adult ⊑ Person
Adult(TC_001)
Sonuc: Person(TC_001)
Reasoner "olası" değil, zorunlu sonuçları üretir. Bu yüzden çıkarım güvenilirdir: kaynak veri doğruysa sonuç da doğrudur.
Reasoner'ın üç görevi
| Görev | Soru | Alerji ontolojisinde |
| Tutarlılık | Ontoloji çelişkili mi? | Bir birey hem Person hem Product mu? |
| Sınıflandırma | Hangi sınıf hangisinin altında? | RiskyProduct ⊑ Product |
| Gerçekleme | Her birey hangi sınıfların üyesi? | TC_001 → PersonAtRisk, Adult |
isConsistent()
getSubClasses()
getInstances()
Nasıl çalışır? Tableau yöntemi
- Reasoner doğrudan "kanıtlamaz"; çelişki arar.
- "TC_001 riskli değil" varsayımı eklenir; model kurulmaya çalışılır.
- Model kurulamıyorsa varsayım yanlıştır → TC_001 risklidir.
- Bu yönteme refutation (çürütme) denir; SAT çözücülerdeki mantığın aynısı.
Sonuç: OWL 2 DL için karar verilebilir ama en kötü durumda 2-NEXPTIME. Pratikte optimizasyonlar sayesinde binlerce bireyde saniyeler sürer.
DL reasoner ile kural motoru
| Boyut | DL reasoner (HermiT) | Kural motoru (Drools) |
| Yöntem | Tableau, çelişki arama | İleri zincirleme, eşleme |
| Dünya | Açık (OWA) | Kural gövdesi eşleşirse tetikler |
| Aritmetik | Yok | Built-in ile var |
| Sonuç nerede | Bellekte, geçici | Ontolojiye yazılabilir |
| Anonim birey | Görür | Görmez (DL-safe) |
Projede ikisi sırayla çalışır: SWRL hesaplar ve zincirler, HermiT sınıflandırır ve denetler.
03
Reasoner Ailesi
HermiT, Pellet/Openllet, JFact, ELK, FaCT++ ve kural tabanlı yaklaşımlar.
Hangi reasoner, ne için?
| Reasoner | Yöntem / profil | Güçlü yanı | Projede |
| HermiT | Hypertableau, OWL 2 DL | Karmaşık kısıtlarda hızlı | Varsayılan |
| Pellet / Openllet | Tableau, OWL 2 DL | SWRL desteği, açıklama | Alternatif |
| JFact | FaCT++ Java portu | Saf Java, kararlı | Yedek |
| ELK | Kural tabanlı, OWL 2 EL | Çok büyük taksonomi | Uygun değil |
| FaCT++ | C++ , OWL 2 DL | Hız | Yerel kütüphane gerekir |
Alerji ontolojisi only, sayı kısıtı ve ayrıklık kullandığı için DL profilindedir — ELK bu kısıtları göz ardı eder.
HermiT ile Pellet arasındaki seçim
HermiT 1.4.5
- Hypertableau: daha az dallanma
- Sayı kısıtlarında güçlü
- SWRL'i doğrudan yürütmez
- Aktif bakımda
Pellet / Openllet 2.6
- SWRL kurallarını kendi işler
- Açıklama (explanation) üretir
- SPARQL-DL desteği
- Pellet arşivde; Openllet sürdürülüyor
Projede HermiT + SWRLAPI/Drools ikilisini seçtik: kural yürütme ile DL çıkarımını ayırmak, hangi sonucun nereden geldiğini izlenebilir kılıyor.
Kural tabanlı yaklaşımlar: ROWL ve akrabaları
| Araç | Ne yapar | Alerji projesinde kullanımı |
| ROWL | Protégé eklentisi: SWRL kuralını OWL aksiyomlarına çevirir | S3 gibi kuralları kısıt olarak yazıp saf DL çıkarımı almak |
| SWRLAPI + Drools | Kuralı üretim kuralına çevirip yürütür | Projenin ana yolu; aritmetik için zorunlu |
| OWL 2 RL / RDFox | Materyalizasyon, ölçekli | Milyonlarca ürün senaryosu |
| SPIN / SHACL Rules | SPARQL tabanlı kural | RDF yığını üzerinde alternatif |
ROWL'un sınırı: aritmetik ve built-in çeviremez. S4 (BMI) kuralı OWL'a çevrilemez — bu yüzden kural motoru vazgeçilmezdir.
ROWL: kuraldan aksiyoma çeviri
SWRL kuralı
Product(?u) ^ Contain(?u, ?f)
^ Triggers(?f, ?al)
-> RiskyProduct(?u)
ROWL çıktısı (OWL kısıtı)
Product and
(Contain some
(Triggers some Allergy))
SubClassOf RiskyProduct
Kazanç: kural motoru gerekmez, HermiT tek başına çıkarır. Kayıp: hangi katkının suçlu olduğu bilgisi üretilemez — S6'nın Effected_Allergen çıktısı kaybolur.
04
OWLReasoner Arayüzü
Kısa kod parçalarıyla, adım adım.
Adım 1 — Reasoner'ı oluştur
OWLReasonerFactory rf =
new ReasonerFactory(); // HermiT
OWLReasoner r = rf.createReasoner(ont);
- Tek arayüz, çok motor: OWLReasoner.
- Motoru değiştirmek için yalnızca fabrika satırı değişir.
- Reasoner ontolojinin o anki hâlini alır.
HermiT : new org.semanticweb.HermiT.ReasonerFactory()
Openllet: new openllet.owlapi.OpenlletReasonerFactory()
JFact : new uk.ac.manchester.cs.jfact.JFactFactory()
ELK : new org.semanticweb.elk.owlapi.ElkReasonerFactory()
Adım 2 — Tutarlılık denetimi
if (!r.isConsistent()) {
System.out.println("TUTARSIZ!");
return;
}
// Tatmin edilemeyen siniflar
r.getUnsatisfiableClasses()
.getEntitiesMinusBottom()
.forEach(System.out::println);
- Tutarsız ontolojide her şey doğrudur — sorgular anlamsızlaşır.
- Bu yüzden her zaman ilk bu denetim yapılır.
- Unsatisfiable sınıf: üyesi hiç olamayan sınıf. Genelde model hatasıdır.
Adım 3 — Sınıflandırma
OWLClass person = cls("Person");
// Dogrudan alt siniflar
r.getSubClasses(person, true)
.getFlattened().forEach(System.out::println);
// Tum ust siniflar
r.getSuperClasses(cls("PersonAtRisk"), false)
.getFlattened().forEach(System.out::println);
- true = yalnızca doğrudan, false = tüm hiyerarşi.
- Dönen tip NodeSet: eşdeğer sınıflar aynı düğümde gruplanır.
- getFlattened() ile düz kümeye çevrilir.
Adult · PersonAtRisk · LactoseIntolerantPerson (çıkarıldı)
Adım 4 — Gerçekleme: birey ↔ sınıf
Sınıfın üyeleri
r.getInstances(
cls("PersonAtRisk"), false)
.getFlattened()
.forEach(System.out::println);
Bireyin tipleri
r.getTypes(
ind("TC_001"), false)
.getFlattened()
.forEach(System.out::println);
getInstances → TC_001 TC_002 TC_003 TC_004
getTypes → Person, Adult, PersonAtRisk, LactoseIntolerantPerson
Adım 5 — Çıkarılan ilişki değerleri
// Cikarilan nesne ozelligi degerleri
r.getObjectPropertyValues(
ind("TC_001"), op("Effected_Allergen"))
.getFlattened().forEach(System.out::println);
// Cikarilan veri ozelligi degerleri
r.getDataPropertyValues(
ind("TC_001"), dp("hasBMI"))
.forEach(l -> System.out.println(l.getLiteral()));
- Kritik ayrım: EntitySearcher yalnızca bildirilmişi okur; reasoner çıkarılanı da verir.
- Alt özellik hiyerarşisi burada devreye girer: Lactose_Allergen değerleri üst özellikte de görünür.
Adım 6 — Belirli bir sonucu test et
OWLAxiom soru = df.getOWLClassAssertionAxiom(
cls("PersonAtRisk"), ind("TC_001"));
System.out.println(r.isEntailed(soru)); // true
// Sinif iliskisi testi
System.out.println(r.isEntailed(
df.getOWLSubClassOfAxiom(
cls("RiskyProduct"), cls("Product"))));
- Bütün çıkarımı listelemek yerine tek soruyu sormak çok daha hızlıdır.
- Birim testleri için ideal: beklenen çıkarımı JUnit ile doğrulayın.
- false dönmesi "yanlış" değil, "gerektirilmiyor" demektir (OWA).
Aynı kod, üç farklı motor
void rapor(OWLReasonerFactory rf, String ad) {
long t0 = System.currentTimeMillis();
OWLReasoner r = rf.createReasoner(ont);
r.precomputeInferences(InferenceType.CLASS_ASSERTIONS);
int n = r.getInstances(cls("PersonAtRisk"), false)
.getFlattened().size();
System.out.printf("%-10s risk=%d %d ms%n",
ad, n, System.currentTimeMillis() - t0);
r.dispose();
}
HermiT risk=4 812 ms
Openllet risk=4 1104 ms
JFact risk=4 935 ms
Sonuçlar aynı olmalıdır — farklı çıkıyorsa ya ontoloji DL dışındadır ya da bir motor kısıtı göz ardı ediyordur.
05
SWRL + Reasoner Birlikte
Sekiz adımlı akış ve doğru sıra.
Projenin sekiz adımlı akışı
| Adım | İş | Araç |
| 1 | Ontolojiyi yükle | OWL API |
| 2 | Envanter raporla | OWL API |
| 3 | Ön denetim: tutarlılık + boş sınıflar | HermiT |
| 4 | Kural motorunu kur | SWRLAPI |
| 5 | infer() — kuralları çalıştır | Drools |
| 6 | SQWRL ile raporla | SQWRL |
| 7 | Son denetim: sınıflandırma + gerçekleme | HermiT |
| 8 | Çıkarımı kalıcı yaz | OWL API |
Adım 3 ve 7 aynı denetimdir — fark önemlidir: kural öncesi boş olan PersonAtRisk sonrasında dolmalıdır.
Adım 3 — Kural öncesi denetim
OWLReasoner r = new ReasonerFactory()
.createReasoner(ont);
System.out.println("Tutarli: " + r.isConsistent());
System.out.println("PersonAtRisk: " +
r.getInstances(cls("PersonAtRisk"), false)
.getFlattened());
r.dispose();
Tutarli: true
PersonAtRisk: []
Boş liste beklenen sonuçtur: risk bilgisi henüz üretilmemiştir. Bu satır, sistemin çalıştığının kanıtı olacak.
Adım 4–5 — Kuralları çalıştır
SWRLRuleEngine engine =
SWRLAPIFactory.createSWRLRuleEngine(ont);
System.out.println("Kural: " +
engine.getSWRLRules().size());
engine.infer(); // Drools ileri zincirleme
- infer() üç işi birden yapar: aktar → çalıştır → geri yaz.
- Protégé'deki üç düğmenin kod karşılığıdır.
- Sonuçlar ASSERTED olarak yazılır — artık bildirilmiş bilgidir.
Kural: 7
infer() tamamlandi (812 ms) — 14 aksiyom eklendi
Adım 7 — Kural sonrası denetim
// YENI reasoner: ontoloji degisti
OWLReasoner r2 = new ReasonerFactory().createReasoner(ont);
for (String c : new String[]{"PersonAtRisk", "Adult", "RiskyProduct"})
System.out.println(c + " = " +
r2.getInstances(cls(c), false).getFlattened());
PersonAtRisk = [TC_001, TC_002, TC_003, TC_004]
Adult = [TC_001, TC_003, TC_004]
RiskyProduct = [EAN_00001, EAN_00002, EAN_00003, EAN_00004]
Önemli: eski reasoner nesnesi güncellenmez. Ontoloji değiştiyse yeni reasoner oluşturun veya flush() çağırın.
Tampon sorunu: flush()
Hatalı
man.addAxiom(ont, yeniAksiyom);
r.getInstances(...);
// eski sonuc doner
Doğru
man.addAxiom(ont, yeniAksiyom);
r.flush();
r.getInstances(...);
Reasoner varsayılan olarak tamponlu (buffering) çalışır: performans için değişiklikleri biriktirir. BufferingMode.NON_BUFFERING ile otomatik yenileme seçilebilir, ama yavaştır.
Adım 8 — Çıkarımı kalıcı yaz
List<InferredAxiomGenerator<? extends OWLAxiom>> gens =
Arrays.asList(new InferredClassAssertionAxiomGenerator(),
new InferredSubClassAxiomGenerator(),
new InferredPropertyAssertionGenerator());
new InferredOntologyGenerator(r2, gens).fillOntology(df, ont);
man.saveOntology(ont, new RDFXMLDocumentFormat(),
IRI.create(new File("ALLERGY_INFERRED.owl").toURI()));
Artık PersonAtRisk(TC_001) dosyada yazılıdır. Reasoner olmayan bir istemci bile bu bilgiyi okuyabilir — materyalizasyon budur.
Hangi çıkarımı yazmalı?
| Generator | Yazdığı | Projede |
| InferredClassAssertionAxiomGenerator | Birey → sınıf | Gerekli (PersonAtRisk) |
| InferredSubClassAxiomGenerator | Sınıf hiyerarşisi | Gerekli (RiskyProduct) |
| InferredPropertyAssertionGenerator | İlişki değerleri | Gerekli (Effected_Allergen) |
| InferredEquivalentClassAxiomGenerator | Eşdeğerlikler | İsteğe bağlı |
| InferredDisjointClassesAxiomGenerator | Ayrıklıklar | Gereksiz — dosyayı şişirir |
Hepsini yazmak dosyayı katbekat büyütür ve okunmaz kılar. Yalnızca tüketicinin ihtiyacı olanı yazın.
06
Hata Ayıklama ve Performans
Gerekçe üretme, tutarsızlık avı, ölçekleme.
Gerekçe üretme: neden bu sonuç?
ExplanationGenerator<OWLAxiom> eg =
new InconsistentOntologyExplanationGeneratorFactory(
rf, () -> 60000L)
.createExplanationGenerator(ont);
eg.getExplanations(soru, 3)
.forEach(ex -> ex.getAxioms()
.forEach(System.out::println));
TC_001 hasAllergy Lactose
TC_001 ChooseProduct EAN_00004
EAN_00004 Contain Nisin
Nisin Triggers Lactose
S6 ⇒ Effected_Allergen
S7 ⇒ PersonAtRisk
Protégé'deki Explain düğmesinin kod karşılığı. Gıda güvenliği raporlarında gerekçe göstermek yasal bir gerekliliktir.
Tutarsızlığı bulmak: örnek olay
Eklenen hatalı aksiyom
// Nisin hem katki hem alerji
add(df.getOWLClassAssertionAxiom(
cls("Allergy"), ind("Nisin")));
Reasoner çıktısı
isConsistent() = false
Gerekce:
FoodAdditives(Nisin)
Allergy(Nisin)
DisjointClasses(...)
Ayrıklık aksiyomu olmasaydı bu hata hiç fark edilmezdi: Nisin sessizce iki sınıfa ait olur, sorgular garipleşirdi. Aksiyomların bedeli budur — hata yakalarlar.
Performans: ne yavaşlatır?
| Neden | Etki | Çözüm |
| Her sorguda yeni reasoner | Baştan sınıflandırma | Tek nesne + flush() |
| NON_BUFFERING mod | Her ekleme yeniden hesap | Tamponlu kullan |
| Nitelikli sayı kısıtları | Dallanma artar | Gerçekten gerekliyse kullan |
| Çok fazla sameAs | Birey birleştirme maliyeti | HasKey ile sınırlı tut |
| Kural sayısı × birey sayısı | Drools eşleme patlaması | Genel kural (S6) tercih et |
r.precomputeInferences(InferenceType.CLASS_ASSERTIONS, InferenceType.CLASS_HIERARCHY);
Protégé ekranı ↔ kod eşlemesi
Reasoner › HermiT 1.4.5 › Start reasoner
Protégé menüsüKod
Start reasonerrf.createReasoner(ont)
Synchronise reasonerr.flush()
Inferred class hierarchyr.getSubClasses(c, true)
Instances (inferred)r.getInstances(c, false)
ExplainExplanationGenerator
Export inferred axiomsInferredOntologyGenerator
Şematik gösterim. Protégé'de yaptığınız her işlemin bir kod karşılığı vardır — arayüz yalnızca API'nin bir yüzüdür.
07
Ödev ve Proje Adımı
Üç reasoner, tek rapor.
Ödev 9 — Reasoner karşılaştırması
- Ontolojinizi HermiT, Openllet ve JFact ile çalıştırıp süre ve sonuç karşılaştırın.
- Kural öncesi/sonrası PersonAtRisk farkını raporlayın.
- Bilinçli bir tutarsızlık ekleyip gerekçesini kodla yazdırın.
- Üç generator ile *_INFERRED.owl üretin; aksiyom sayısı artışını gösterin.
- Bir beklenen çıkarımı isEntailed ile JUnit testine dönüştürün.
Teslim
Karşılaştırma tablosu + gerekçe çıktısı + iki .owl dosyası + test sınıfı + 3 sayfa rapor.
Çözümü Hafta 10'un başında ele alacağız.
Değerlendirme ölçütleri
| Ölçüt | Ağırlık | Beklenen |
| Reasoner karşılaştırması | 25% | Üç motor, aynı sonuç, süre ölçümü |
| Kural öncesi/sonrası fark | 20% | Boş → dolu gösterilmiş |
| Gerekçe analizi | 20% | Aksiyom zinciri yorumlanmış |
| Materyalizasyon | 20% | Generator seçimi gerekçeli |
| Test | 15% | isEntailed testi geçiyor |
Kaynaklar ve referanslar
- Glimm, B., Horrocks, I., Motik, B., Stoilos, G., Wang, Z. — HermiT: An OWL 2 Reasoner, Journal of Automated Reasoning, 2014.
- Sirin, E., Parsia, B., Grau, B.C., Kalyanpur, A., Katz, Y. — Pellet: A Practical OWL-DL Reasoner, Journal of Web Semantics, 2007.
- Kazakov, Y., Krötzsch, M., Simančík, F. — The Incredible ELK, Journal of Automated Reasoning, 2014.
- Tsarkov, D., Horrocks, I. — FaCT++ Description Logic Reasoner, IJCAR 2006.
- Horridge, M., Bechhofer, S. — The OWL API, Semantic Web Journal, 2011.
- Sarker, M.K., Krisnadhi, A., Hitzler, P. — OWLAx / ROWL: Protégé plugins, ISWC Demos.
- Baader, F. et al. — The Description Logic Handbook, 2nd ed., Cambridge.
Özet • 1 / 2
Çıkarım ve reasoner'lar
- Çıkarım "olası" değil zorunlu sonuçları üretir; yöntem çelişki aramaktır.
- Üç görev: tutarlılık, sınıflandırma, gerçekleme.
- HermiT DL için varsayılan; Openllet SWRL ve açıklama sunar; ELK yalnızca EL profili.
- ROWL kuralı OWL kısıtına çevirir ama aritmetik çeviremez.
- Tutarsız ontolojide her şey doğrudur — denetim daima ilk adımdır.
Özet • 2 / 2
API kullanımı ve sonraki adım
- Motoru değiştirmek için tek satır yeter: fabrika.
- Ontoloji değiştiyse flush() ya da yeni reasoner.
- isEntailed tek soruyu sormanın en hızlı yolu.
- Materyalizasyonda yalnızca gerekli generator'ları seçin.
Hafta 10'da
SWRL API & SQWRL: kuralları kodla yönetmek, sorgu dili, uçtan uca çalışan sistem ve proje teslimi.
Ayrıca: Ödev 9'un ayrıntılı çözümü.
Tekrar Soruları
Kendinizi sınayın
- Reasoner neden çelişki arar?
- Tutarsız ontolojide sorgu neden anlamsızdır?
- Unsatisfiable sınıf neye işaret eder?
- ELK bu projede neden uygun değil?
- ROWL neyi çevirebilir, neyi çeviremez?
- flush() unutulursa ne olur?
- getInstances(c, true) ile false farkı?
- Neden bütün generator'ları yazmamalı?
Alıştırma • Sınıf içi
Çıkarımı tahmin edin
Ontolojiye şu aksiyom eklenir ve HermiT çalıştırılır:
Ascorbic_Acid Triggers Lactose .
Sorular
- Hangi kişi için yeni Effected_Allergen üretilir?
- PersonAtRisk kümesi değişir mi?
- flush() çağırmadan sonucu görebilir misiniz?
- Bu çıkarım hangi kuraldan gelir: S3 mü S6 mı?
Çözüm Hafta 10'da.